﻿using System;
using System.Text.RegularExpressions;

namespace AcademicPlanner.Framework.Libraries.Validation
{
	/// <summary>
	/// Provides static validation methods for <c>string</c>s.
	/// </summary>
	/// <version>1.0</version>
	/// <since>1.0</since>
	public static class StringValidator
	{
		/// <summary>
		/// Regular expression for a valid email address: "^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$".
		/// </summary>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static readonly string EMAIL_REGEXP = @"^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$";

		/// <summary>
		/// Regular expression for words with letters only: "^([a-zA-Z]+\s*)+$".
		/// </summary>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static readonly string ALPHA_REGEXP = @"^([a-zA-Z]+\s*)+$";

		/// <summary>
		/// Regurlar expression for words with letters and digits and "_" only: "^([a-zA-Z0-9_]+\s*)+$".
		/// </summary>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static readonly string ALNUM_REGEXP = @"^([a-zA-Z0-9_]+\s*)+$";


		/// <summary>
		/// Checks whether the given <c>string</c> is blank or not i.e.
		/// it contains at least one character.
		/// </summary>
		/// <param name="pVal">The <c>string</c> to check.</param>
		/// <returns>Whether the <c>string</c> is blank or not.</returns>
		/// <seealso cref="M:ContainsAtLeast"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static bool IsNotBlank(string pVal)
		{
			return ContainsAtLeast(pVal, 1);
		}

		/// <summary>
		/// Checks whether the given <c>string</c> is a valid email address or not i.e.
		/// it matches the <c>EMAIL_REGEXP</c> regualar expression.
		/// </summary>
		/// <param name="pVal">The <c>string</c> to check.</param>
		/// <returns>Whether the <c>string</c> is a valid email address or not.</returns>
		/// <seealso cref="M:Matches"/>
		/// <seealso cref="P:EMAIL_REGEXP"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static bool IsEmailAddress(string pVal)
		{
			return Matches(pVal, EMAIL_REGEXP);
		}

		/// <summary>
		/// Checks whether the given <c>string</c> matches the given regualar expression.
		/// </summary>
		/// <param name="pVal">The <c>string</c> to check.</param>
		/// <param name="pRegex">The regular expression to check against.</param>
		/// <returns>Whether the <c>string</c> matches the given regualar expression.</returns>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static bool Matches(string pVal, string pRegex)
		{
			return Regex.IsMatch(pVal, pRegex);
		}

		/// <summary>
		/// Checks whether the given <c>string</c> is words with letters only i.e.
		/// it matches the <c>ALPHA_REGEXP</c> regualar expression.
		/// </summary>
		/// <param name="pVal">The <c>string</c> to check.</param>
		/// <returns>Whether the <c>string</c> is words with letters only or not.</returns>
		/// <seealso cref="M:Matches"/>
		/// <seealso cref="P:ALPHA_REGEXP"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static bool IsAlpha(string pVal)
		{
			return Matches(pVal, ALPHA_REGEXP);
		}

		/// <summary>
		/// Checks whether the given <c>string</c> is words with letters and digits only i.e.
		/// it matches the <c>ALNUM_REGEXP</c> regualar expression.
		/// </summary>
		/// <param name="pVal">The <c>string</c> to check.</param>
		/// <returns>Whether the <c>string</c> is words with letters and digits only or not.</returns>
		/// <seealso cref="M:Matches"/>
		/// <seealso cref="P:ALNUM_REGEXP"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static bool IsAlphaNumeric(string pVal)
		{
			return Matches(pVal, ALNUM_REGEXP);
		}

		/// <summary>
		/// Checks whether the given <c>string</c> contains at least the the given
		/// number of characters.
		/// </summary>
		/// <param name="pVal">The <c>string</c> to check.</param>
		/// <param name="pMinChars">The minimum number of characters the <c>string</c> should have.</param>
		/// <returns>Whether the <c>string</c> contains at least the the given number of characters.</returns>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static bool ContainsAtLeast(string pVal, int pMinChars)
		{
			return (pVal.Trim().Length >= pMinChars);
		}

		/// <summary>
		/// Checks whether the given <c>string</c> contains at most the the given
		/// number of characters.
		/// </summary>
		/// <param name="pVal">The <c>string</c> to check.</param>
		/// <param name="pMaxChars">The maximum number of characters the <c>string</c> should have.</param>
		/// <returns>Whether the <c>string</c> contains at most the the given number of characters.</returns>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static bool ContainsAtMost(string pVal, int pMaxChars)
		{
			return (pVal.Trim().Length <= pMaxChars);
		}

		/// <summary>
		/// Checks whether two <c>string</c>s are identical i.e. have the same characters
		/// after trimming.
		/// </summary>
		/// <param name="pVal">The first <c>string</c>.</param>
		/// <param name="pComparee">The second <c>string</c>.</param>
		/// <returns>Whether the two <c>string</c>s are identical or not.</returns>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static bool IsIdenticalTo(string pVal, string pComparee)
		{
			return pVal.Trim().Equals(pComparee.Trim());
		}
	}
}
